package com.bangcommunity.bbframe.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;

public class RetryHelper {
    private static Logger logger = LoggerFactory.getLogger(RetryHelper.class);
    private static int[] steps = new int[] { 1, 1, 2 };

    public static <T extends Serializable> T retry(int times, RetryAble<T> tryable) {
        return retry(times, null,tryable);
    }
    public static <T extends Serializable> T retry(int times, RetryAble<T> preTry, RetryAble<T> tryable) {
        int c = Math.max(times, 0);
        int time = 0;
        Throwable exception = null;
        while (time++ < c) {
            try {
                if(null != preTry){
                    T retry = preTry.retry(time);
                    if(null != retry){
                        return retry;
                    }
                }
                return tryable.retry(time);
            } catch (Throwable e) {
                logger.error("dotry exception: {}", time,e);
                exception = e;
            }
            try {
                Thread.sleep(getStepIndex(time) * 1000);
            } catch (InterruptedException e) {
                // swollow
            }
        }
        throw new RuntimeException(exception);
    }

    private static int getStepIndex(int times) {
        times = Math.max(0, times - 1);
        int stepsize = steps.length;
        return times % stepsize;
    }

    public static interface RetryAble<T extends Serializable> {
        /**
         *
         * @param time
         *            第几次执行
         */
        public T retry(int time) throws Throwable;
    }


    public static void main(String[] args) {
        RetryHelper.retry(5, time -> {
                    if(time < 4){
                        throw new Exception("test");
                    }
                    return 1;
                });
    }

}
